// depends on Array.js, Class.js, DOM.js, Function.js, Number.js, Object.js, String.js
(function() {
	window.Prototype = {
		emptyFunction: function() {},
		Browser: {
			IE: navigator.userAgent.match(/MSIE \d/),
			Opera: Object.prototype.toString.call(window.opera) == '[object Opera]'
		},
		K: function(v) { return v; }
	};
	Array.prototype.flatten = function flatten() {
    return this.inject([], function(array, value) {
      if (Object.isArray(value))
        return array.concat(value.flatten());
      array.push(value);
      return array;
    });
  };
	window.$R = function $R() {
		return [0, 1, 2];
	};
	Element.addMethods({
		getDimensions: function getDimensions() {
			var display = this.getStyle('display');
			if (display != 'none' && display != null) // Safari bug
				return {width: this.offsetWidth, height: this.offsetHeight};

			var els = this.style;
			var originalVisibility = els.visibility;
			var originalPosition = els.position;
			var originalDisplay = els.display;
			els.visibility = 'hidden';
			if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari
				els.position = 'absolute';
			els.display = 'block';
			var originalWidth = this.clientWidth;
			var originalHeight = this.clientHeight;
			els.display = originalDisplay;
			els.position = originalPosition;
			els.visibility = originalVisibility;
			return {width: originalWidth, height: originalHeight};
		},
		makeClipping: function makeClipping() {
			if (this._overflow) {
				return this;
			}
			this._overflow = this.getStyle('overflow') || 'auto';
			if (this._overflow !== 'hidden') {
				this.style.overflow = 'hidden';
			}
			return this;
		},
		undoClipping: function undoClipping() {
			if (!this._overflow) {
				return this;
			}
			this.style.overflow = this._overflow == 'auto' ? '' : this._overflow;
			this._overflow = null;
			return this;
		},
		makePositioned: function makePositioned() {
			var pos = this.getStyle('position');
			if (pos == 'static' || !pos) {
				this._madePositioned = true;
				this.style.position = 'relative';
				if (Prototype.Browser.Opera) {
					this.style.top = 0;
					this.style.left = 0;
				}
			}
			return this;
		},
		undoPositioned: function undoPositioned() {
			if (this._madePositioned) {
				this._madePositioned = undefined;
				this.style.position =
					this.style.top =
					this.style.left =
					this.style.bottom =
					this.style.right = '';
			}
			return this;
		},
		cleanWhitespace: function cleanWhitespace() {
			var node = this.firstChild;
			while (node) {
				var nextNode = node.nextSibling;
				if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) {
					this.removeChild(node);
				}
				node = nextNode;
			}
			return this;
		},
		cumulativeOffset: function cumulativeOffset(element) {
			var valueT = 0, valueL = 0;
			do {
				valueT += element.offsetTop  || 0;
				valueL += element.offsetLeft || 0;
				element = element.offsetParent;
			} while (element);

			return Element._returnOffset(valueL, valueT);
		}
	});
	if (!Element.Methods.down) {
		Element.Methods.down = function down() {
			var node = this.firstChild;
			while (node) {
				if (node.nodeType != 3) {
					return node;
				}
				node = node.nextSibling;
			}
			return undefined;
		};
	}
	Element._returnOffset = function(l, t) {
		var result = [l, t];
		result.left = l;
		result.top = t;
		return result;
	};
	document.viewport = {
		getScrollOffsets: function() {
			return Element._returnOffset(
				window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
				window.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop);
		}
	};
	window.Enumerable = Class.create({

	});
	var uid = +new Date;
	var Hash = Class.create({
		initialize: function initialize(data) {
			this._data = data || {};
		},
		set: function set(k, v) {
			this._data[k] = v;
			return this;
		},
		get: function get(k) {
			return this._data[k];
		},
		reject: function reject(iterator, context) {
			var results = {};
			for (var k in this._data) {
				if (!iterator.call(context, this._data[k], k)) {
					results[k] = this._data[k];
				}
			}
			return new Hash(results);
		},
		each: function each(iterator, context) {
			for (var k in this._data) {
				iterator.call(context, this._data[k], k);
			}
			return this;
		},
		map: function map(iterator, context) {
			iterator = iterator || Prototype.K;
			var results = [];
			this.each(function(value, index) {
				results.push(iterator.call(context, value, index));
			});
			return results;
		}
	});
	window.$H = function $H() {
		return new Hash;
	};
	window.$w = function $w(s) {
		return s.split(' ');
	};
	window.onload = function() {
		var demethodized = {};
		for (var name in Effect.Methods) {
			(function(name, fn) {
				demethodized[name] = function() {
					var args = Array.prototype.slice.call(arguments);
					return fn.apply(null, [this].concat(args));
				};
			})(name, Effect.Methods[name]);
		}
		Element.addMethods(demethodized);
	};
})();
